package com.zeyu.framework.monitors.server.web;

import com.google.common.collect.Lists;
import com.zeyu.framework.core.persistence.Page;
import com.zeyu.framework.core.web.BaseController;
import com.zeyu.framework.core.web.Result;
import com.zeyu.framework.modules.sys.utils.UserUtils;
import com.zeyu.framework.monitors.server.ServerCollector;
import com.zeyu.framework.monitors.server.entity.CPUStatus;
import com.zeyu.framework.monitors.server.entity.DiskStatus;
import com.zeyu.framework.monitors.server.entity.NetInfoStatus;
import com.zeyu.framework.monitors.server.entity.ProcStatus;
import com.zeyu.framework.monitors.server.entity.ServerStatus;
import com.zeyu.framework.monitors.server.service.ServerCPUService;
import com.zeyu.framework.monitors.server.service.ServerService;
import com.zeyu.framework.tools.report.charts.ChartData;
import com.zeyu.framework.tools.report.dynamic.ReportUtils;
import com.zeyu.framework.utils.Collections3;
import com.zeyu.framework.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * server 监控和操作controller
 * Created by zeyuphoenix on 16/8/27.
 */
@Controller
@RequestMapping(value = "/monitors/server")
public class ServerController extends BaseController {

    // ================================================================
    // Constants
    // ================================================================

    // ================================================================
    // Fields
    // ================================================================

    @Autowired
    private ServerCollector serverCollector;

    @Autowired
    private ServerService serverService;

    @Autowired
    private ServerCPUService serverCPUService;

    // ================================================================
    // Constructors
    // ================================================================

    // ================================================================
    // Methods from/for super Interfaces or SuperClass
    // ================================================================

    // ================================================================
    // Public or Protected Methods
    // ================================================================

    /**
     * 页面
     */
    @RequestMapping(value = {"index", ""})
    public String index() {

        return "modules/monitors/server";
    }

    /**
     * 获取最后一次监控的基本信息,这些信息不保存数据库
     */
    @ResponseBody
    @RequestMapping("current")
    public ServerStatus currentSatatus() {
        ServerStatus serverStatus = serverCollector.getServerStatus();
        if (serverStatus == null) {
            // 未扫描过则扫描一次
            serverStatus = serverCollector.getCurrentServerStatus();
        }
        serverStatus.setHostName(DateUtils.formatDateTimeLocal(serverStatus.getUptime() * 1000L));
        return serverStatus;
    }

    /**
     * 获取server的disk列表
     */
    @RequestMapping(value = "diskList")
    @ResponseBody
    public Page<DiskStatus> diskList(HttpServletRequest request) {
        Page<DiskStatus> page = new Page<>(request);
        page.setCount(1);
        page.setList(serverCollector.getDiskStatusList());
        return page;
    }

    /**
     * 获取server的process列表
     */
    @RequestMapping(value = "procList")
    @ResponseBody
    public Page<ProcStatus> procList(HttpServletRequest request) {
        Page<ProcStatus> page = new Page<>(request);
        page.setCount(1);
        page.setList(serverCollector.getProcStatusList());
        return page;
    }

    /**
     * 获取 server 的 network info 列表
     */
    @RequestMapping(value = "netList")
    @ResponseBody
    public Page<NetInfoStatus> netList(HttpServletRequest request) {
        Page<NetInfoStatus> page = new Page<>(request);
        page.setCount(1);
        page.setList(serverCollector.getNetInfoStatusList());
        return page;
    }

    /**
     * server的监控图表
     * 监控断掉的问题没办法
     */
    @RequestMapping(value = "chartData")
    @ResponseBody
    public ChartData chartData(int type) {

        ChartData chartData = new ChartData();

        // 默认查询是1分钟一次,则1小时60个,一天1440个,一个月44000以内,使用带浮动条的查看7天,也就是10000左右
        Page<ServerStatus> page = new Page<>();
        page.getDatatablesCriterias().setStart(0);
        page.getDatatablesCriterias().setLength(10000);
        Page<ServerStatus> serverStatusPage = serverService.findPage(page, new ServerStatus());
        if (!Collections3.isEmpty(serverStatusPage.getList())) {
            // 角度
            List<String> xAxis = Lists.newArrayList();
            // 指标
            List<List<Number>> series = Lists.newArrayList();

            // type -->  1:物理内存   2:缓冲区内存  3:jvm

            // 转换数据
            for (ServerStatus serverStatus : serverStatusPage.getList()) {
                xAxis.add(DateUtils.formatDate(serverStatus.getTime(), "dd日HH:mm"));
                if (type == 1) {
                    // 物理内存
                    ReportUtils.addSerie(series, 3);
                    // '总物理内存',
                    series.get(0).add(serverStatus.getTotalMemory() * 1024L);
                    // '已使用的物理内存',
                    series.get(1).add(serverStatus.getUsedMemory() * 1024L);
                    // '剩余的物理内存',
                    series.get(2).add(serverStatus.getFreeMemory() * 1024L);

                } else if (type == 2) {
                    // 缓冲区内存
                    ReportUtils.addSerie(series, 3);
                    // '总缓冲区内存',
                    series.get(0).add(serverStatus.getSwapTotalMemory() * 1024L);
                    // '已使用的缓冲区内存',
                    series.get(1).add(serverStatus.getSwapUsedMemory() * 1024L);
                    // '剩余的缓冲区内存',
                    series.get(2).add(serverStatus.getSwapFreeMemory() * 1024L);

                } else if (type == 3) {
                    // jvm
                    ReportUtils.addSerie(series, 3);
                    // 'JVM总物理内存',
                    series.get(0).add(serverStatus.getJvmTotalMemory());
                    // 'JVM最大物理内存',
                    series.get(1).add(serverStatus.getJvmFreeMemory());
                    // 'JVM剩余物理内存',
                    series.get(2).add(serverStatus.getJvmFreeMemory());
                }
            }


            chartData.setxAxis(xAxis);
            chartData.setSeries(series);
        }

        return chartData;
    }

    /**
     * server的监控图表-cpu
     * 监控断掉的问题没办法
     */
    @RequestMapping(value = "chartDataCPU")
    @ResponseBody
    public ChartData chartDataCPU() {
        ChartData chartData = new ChartData();

        // 获取索引列表
        List<String> indList = serverCPUService.findIndList();
        chartData.setLegends(indList.stream()
                .map(ind -> "CPU " + ind)
                .collect(Collectors.toList())
        );

        // 默认查询是1分钟一次,则1小时60个,一天1440个,一个月44000以内,使用带浮动条的查看7天,也就是10000左右
        Page<CPUStatus> page = new Page<>();
        page.getDatatablesCriterias().setStart(0);
        page.getDatatablesCriterias().setLength(10000 * indList.size());
        Page<CPUStatus> cpuStatusPage = serverCPUService.findPage(page, new CPUStatus());
        if (!Collections3.isEmpty(cpuStatusPage.getList())) {
            // 角度
            List<String> xAxis = Lists.newArrayList();

            // 指标
            List<List<Number>> series = Lists.newArrayList();
            ReportUtils.addSerie(series, indList.size());
            for (CPUStatus cpuStatus : cpuStatusPage.getList()) {

                for (int i = 0; i < indList.size(); i++) {
                    // cpuStatus.getCpuSysRatio();
                    // cpuStatus.getCpuUsrRatio();
                    if (cpuStatus.getInd() == Integer.valueOf(indList.get(i))) {
                        series.get(i).add(cpuStatus.getCpuRatio() * 100);
                    }
                }
            }
            // 暂时不显示横坐标
            chartData.setxAxis(xAxis);
            chartData.setSeries(series);
        }

        return chartData;
    }

    /**
     * Server释放内存
     */
    @RequestMapping(value = "release")
    @ResponseBody
    public Result release() {
        Result result = new Result();
        if (MODE_DEMO) {
            result.setStatus(Result.ERROR);
            result.setMessage("演示模式，不允许操作!");
            return result;
        }
        if (!UserUtils.getUser().isAdmin()) {
            result.setStatus(Result.ERROR);
            result.setMessage("只能使用管理员用户才可以操作!");
            return result;
        }
        try {
            Runtime.getRuntime().gc();
        } catch (Exception e) {
            logger.error("JVM释放内存失败 .", e);
            result.setStatus(Result.ERROR);
            result.setMessage("Server释放内存失败");
            return result;
        }
        result.setStatus(Result.SUCCESS);
        result.setMessage("Server释放内存成功");
        return result;
    }

    // ================================================================
    // Getter & Setter
    // ================================================================

    // ================================================================
    // Private Methods
    // ================================================================

    // ================================================================
    // Inner or Anonymous Class
    // ================================================================

    // ================================================================
    // Test Methods
    // ================================================================

}
